package com.libra.assemble.web.controller.authority;

import com.google.common.collect.Maps;
import com.libra.assemble.entity.authority.Role;
import com.libra.assemble.entity.authority.Sidebar;
import com.libra.assemble.service.authority.RoleService;
import com.libra.assemble.service.authority.SidebarService;
import com.libra.assemble.web.form.ActionMessageForm;
import com.libra.assemble.xutil.Constants;
import com.libra.assemble.xutil.web.Servlets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.ServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 角色信息管理的业务代理.
 *
 * @author Libra
 */
@Controller
@RequestMapping(value = "/role")
public class RoleController {

    private static Logger logger = LoggerFactory.getLogger(RoleController.class);

    /**
     * 角色管理的业务逻辑
     */
    @Autowired
    private RoleService roleService;

    /**
     * 菜单管理的业务逻辑
     */
    @Autowired
    private SidebarService sidebarService;

    /**
     * 角色列表.
     *
     * @param pageNumber
     * @param pageSize
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    public String list(@RequestParam(value = "page", defaultValue = "1") int pageNumber,
                       @RequestParam(value = "page.size", defaultValue = Constants.PAGE_SIZE_10) int pageSize,
                       Model model, ServletRequest request) {
        Map<String, Object> searchParams = Servlets.getParametersStartingWith(request, "search_");
        Page<Role> roles = roleService.getRole(searchParams, pageNumber, pageSize);

        model.addAttribute("roles", roles);
        // 将搜索条件编码成字符串，用于排序，分页的URL
        model.addAttribute("searchParams", Servlets.encodeParameterStringWithPrefix(searchParams, "search_"));

        return "authority/role-list";
    }

    /**
     * 进入角色创建页面.
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "create", method = RequestMethod.GET)
    public String create(Model model) {
        model.addAttribute("role", new Role());
        model.addAttribute("action", "create");
        return "authority/role-form";
    }

    /**
     * 创建角色.
     *
     * @param newRole
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(@Valid Role newRole, RedirectAttributes redirectAttributes) {
        newRole.setCreateTime(new Date());
        roleService.saveRole(newRole);
        redirectAttributes.addFlashAttribute("message", new ActionMessageForm("success", "很好", "角色［" + newRole.getName() + "］添加成功。"));
        return "redirect:/role/";
    }


    /**
     * 进入角色更新页面.
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping(value = "update/{id}", method = RequestMethod.GET)
    public String update(@PathVariable("id") Long id, Model model) {
        model.addAttribute("role", roleService.getRole(id));
        model.addAttribute("action", "update");
        return "authority/role-form";
    }

    /**
     * 提交更新的角色信息.
     *
     * @param role
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "update", method = RequestMethod.POST)
    public String update(@Valid @ModelAttribute("role") Role role, RedirectAttributes redirectAttributes) {
        logger.info(role.toString());
        roleService.saveRole(role);
        redirectAttributes.addFlashAttribute("message", new ActionMessageForm("success", "很好！", "角色［" + role.getName() + "］已成功更新。"));
        return "redirect:/role";
    }

    /**
     * 删除角色记录.
     *
     * @param id
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "delete/{id}")
    public String delete(@PathVariable("id") Long id, RedirectAttributes redirectAttributes) {
        roleService.deleteRole(id);
        redirectAttributes.addFlashAttribute("message", new ActionMessageForm("warning", "注意：", "角色已被成功删除！"));
        return "redirect:/role";
    }

    /**
     * 进入配置角色菜单信息.
     *
     * @param id
     * @param model
     * @return
     */
    @RequestMapping(value = "sidebar/{id}", method = RequestMethod.GET)
    public String sidebar(@PathVariable("id") Long id, Model model) {
        Role role = roleService.getRole(id);
        model.addAttribute("role", roleService.getRole(id));
        model.addAttribute("topSidebar", sidebarService.getTopSidebar());
        model.addAttribute("isExist", isExist(sidebarService.getAllSidebar(), role.getSidebars()));
        return "authority/role-sidebar";
    }

    /**
     * 配置角色菜单信息.
     *
     * @param role
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "sidebar", method = RequestMethod.POST)
    public String sidebar(@Valid @ModelAttribute("role") Role role, @RequestParam(value = "sidebars.id", required = false) List<Long> sidebarIds, RedirectAttributes redirectAttributes) {
        role.setSidebars(new ArrayList<Sidebar>());
        if (sidebarIds != null) {
            for (Long sidebarId : sidebarIds) {
                role.getSidebars().add(sidebarService.getSidebar(sidebarId));
            }
        }
        roleService.saveRole(role);
        redirectAttributes.addFlashAttribute("message", new ActionMessageForm("success", "很好！", "角色［" + role.getName() + "］成功更新了菜单配置。"));
        return "redirect:/role";
    }

    /**
     * 所有RequestMapping方法调用前的Model准备方法, 实现预处理部分绑定的效果,先根据form的id从数据库查出Role对象,再把Form提交的内容绑定到该对象上。
     * 因为仅update()方法的form中有id属性，因此仅在update时实际执行.
     */
    @ModelAttribute
    public void getRole(@RequestParam(value = "id", defaultValue = "-1") Long id, Model model) {
        if (id != -1) {
            model.addAttribute("role", roleService.getRole(id));
        }
    }

    /**
     * 判断角色是否有查阅菜单权限.
     *
     * @param allSidebar
     * @param roleSidebar
     * @return
     */
    private Map<Long, Boolean> isExist(List<Sidebar> allSidebar, List<Sidebar> roleSidebar) {
        Map<Long, Boolean> map = Maps.newHashMap();
        for (Sidebar sidebar : allSidebar) {
            if (roleSidebar.contains(sidebar)) {
                map.put(sidebar.getId(), true);
            } else {
                map.put(sidebar.getId(), false);
            }
        }

        return map;
    }
}
